const urlHeper = require('url');
const http = require('http');
const https = require('https');
const dayjs = require('dayjs');

/**
 * HTTP/HTTPS请求封装。
 * @param {*} options HTTP/HTTPS请求参数。
 * @param {*} data 请求数据
 * @param {*} protocol 请求协议(HTTP、HTTPS)
 */
let request = function (options, data, protocol = 'https') {
    return new Promise((resolve, reject) => {
        let timeout = options['timeout'];
        let timeoutEventId;

        if (protocol.toLowerCase() == 'https') {
            let client = https.request(options, res => requestHandler(res, resolve, reject, timeoutEventId));

            client.on('timeout', () => {
                if (client.destroy) {
                    client.destroy();
                }

                reject('https请求超时！');
            });
            client.on('error', err => reject(err));

            timeout && (timeoutEventId = setTimeout(() => {
                client.emit('timeout', 'https请求超时！');
            }, timeout));

            if (data) {
                client.write(data);
            }

            client.end();
        } else {
            let client = http.request(options, res => requestHandler(res, resolve, reject, timeoutEventId));

            client.on('timeout', () => {
                if (client.destroy) {
                    client.destroy();
                }

                reject('http请求超时！');
            });

            client.on('error', err => reject(err));

            timeout && (timeoutEventId = setTimeout(() => {
                client.emit('timeout', 'Http请求超时！');
            }, timeout));

            if (data) {
                client.write(typeof data != 'string' ? JSON.stringify(data) : data);
            }

            client.end();
        }
    });
};

/**
 * Http/Https请求结果回调处理。
 * @param {*} response HTTP/HTTPS
 * @param {*} resolve 执行成功的回调。
 * @param {*} reject 执行失败的回调。
 */
function requestHandler (response, resolve, reject, timeoutHandler) {
    if (response.statusCode >= 400) {
        reject(response.statusMessage || response.message);
    } else {
        let body = '';
        let headers = response.headers;

        response.on('data', data => body += data);
        response.on('end', () => {
            timeoutHandler && clearTimeout(timeoutHandler);

            resolve({
                headers: headers,
                body: body
            });
        });

        response.on('error', () => {
            timeoutHandler && clearTimeout(timeoutHandler);

            reject({
                at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
                success: false,
                message: '调用失败！'
            });
        })
    }
}

module.exports = {
    get (url, options) {
        let uri = urlHeper.parse(url);

        let config = {
            method: "GET",
            hostname: uri.hostname,
            port: uri.port,
            path: uri.path,
            timeout: 3000,
            headers: {
                "content-type": "application/json;charset=utf-8"
            }
        };

        // 获取协议
        let protocol = uri.protocol.replace(/\:/g, '');

        Object.assign(config, options);

        return request(config, null, protocol);
    },
    post (url, data, options) {
        let uri = urlHeper.parse(url);

        let config = {
            method: "POST",
            hostname: uri.hostname,
            port: uri.port,
            path: uri.path,
            headers: {
                "content-type": "application/json;charset=utf-8"
            }
        };

        // 获取协议
        let protocol = uri.protocol.replace(/\:/g, '');

        Object.assign(config, options);

        return request(config, data, protocol);
    }
};